﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Gruppe1OOPEksamen {

    public class VareKollektion : IEnumerable {
        //liste der indeholder vare
        private List<Vare> _wrappedList = new List<Vare>();

        //liste der indeholder information om antallet af vare
        private List<VareTæller> _tællerListe = new List<VareTæller>();
        Events eventObj = new Events();

        public VareKollektion(params VareTæller[] varer) {
            foreach (VareTæller v in varer) {
                if (Rækkevidde.StørreEnd<int>(v.AntalVare, 0)) Tilføj(v.VareAtTjekke, v.AntalVare); 
                //Der tilføjes det ønskede antal vare
                _tællerListe.Add(v); 
            }
            //tilføjer VareAntalNåetMin som listener til Eventet EfterVareErMinimum
            eventObj.EfterVareErMinimum += VareAntalNåetMin; 
        }

        #region Enumerators
        public IEnumerator GetEnumerator() {
            //returnere den default enumerator
            return _tællerListe.GetEnumerator(); 
        }

        public IEnumerable<VareTæller> HentOptællendeEnumerator() {
            // Tæller Op
            //(p => p.Pris) er et lambda udtryk
            IEnumerable<VareTæller> vareList = _tællerListe.OrderByDescending(p => p.VareAtTjekke.Pris);
            for (int i = _tællerListe.Count - 1; i >= 0; i--)
                //returnere værdien, men beholder for løkkens state og forløkken køre videre når værdien er blevet returneret
                yield return vareList.ElementAt(i);
        }

        public IEnumerable<VareTæller> HentNedtællendeEnumerator() {
            // Tæller Ned
            IEnumerable<VareTæller> vareList = _tællerListe.OrderByDescending(p => p.VareAtTjekke.Pris);
            for (int i = 0; i < _tællerListe.Count; i++)
                yield return vareList.ElementAt(i);
        }
        #endregion

        #region tilføj/fjern metoder
        public void Tilføj(Vare vare) {
            _wrappedList.Add(vare);
            tælVare(1, vare);
        }
        public void Tilføj(Vare vare, int antal) { 
            //overloader Tilføj(Vare vare)
            for (int i = 0; i < antal; i++) _wrappedList.Add(vare);
            tælVare(antal, vare);
        }

        public bool Fjern(Vare vare) {
            bool fjernet = _wrappedList.Remove(vare);
            tælVare(-1, vare);
            return fjernet;
        }
        public bool Fjern(Vare vare, int antal) { 
            //overloader Fjern(Vare vare)
            for (int i = 0; i < antal; i++) {
                //List.Remove() returnere false hvis den ikke kunne finde objectet den blev bedt om at fjerne, derfor if tjekket
                if (_wrappedList.Remove(vare)) ; 
                else return false;
            }
            tælVare(-antal, vare);
            return true;
        }
        #endregion

        #region søgemetoder
        public List<Vare> FindVareNavn(string søgeord) {
            List<Vare> tmp = new List<Vare>();

            //søger i _tællerliste da hver instance ikke skal returneres mere end engang, 
            //og (det antages) at der kun er en af hver instans i _tællerliste
            foreach (VareTæller vare in _tællerListe)
                if (vare.VareAtTjekke.Navn.Equals(søgeord))
                    tmp.Add(vare.VareAtTjekke);

            return tmp;
        }

        public List<Vare> FindPrisklasse(double min, double maks) {
            List<Vare> tmp = new List<Vare>();

            foreach (VareTæller vare in _tællerListe)
                if (Rækkevidde.ErIndenfor<double>(vare.VareAtTjekke.Pris, maks, min))
                    tmp.Add(vare.VareAtTjekke);

            return tmp;
        }

        public List<Tørretumbler> FindEnergimærke(char mærke) {
            List<Tørretumbler> tmp = new List<Tørretumbler>();

            foreach (VareTæller vare in _tællerListe) {
                if (vare.VareAtTjekke is Tørretumbler) {
                    Tørretumbler t = (Tørretumbler)vare.VareAtTjekke;
                    if(mærke.Equals(t.EnergiMærke)) 
                        tmp.Add(t);
                }
            }

            return tmp;
        }

        public List<Vare> FindSmiley(string smiley) {
            List<Vare> tmp = new List<Vare>();

            foreach (VareTæller vare in _tællerListe)
                if (vare.VareAtTjekke is ISmileyKontrol) {
                    if (vare.VareAtTjekke is Elovn) {
                        Elovn t = (Elovn) vare.VareAtTjekke;
                        if (t.Smiley.Equals(smiley)) tmp.Add(t);
                    }
                    else if (vare.VareAtTjekke is Emhætte) {
                        Emhætte t = (Emhætte) vare.VareAtTjekke;
                        if (t.Smiley.Equals(smiley)) tmp.Add(t);
                    }
                }

            return tmp;
        }
        #endregion

        #region tælvarene
        public bool TilføjMinimumsværdiType(Vare t, int minInd) {
            foreach(VareTæller v in _tællerListe) {
                if (v.VareAtTjekke.ToString().Equals(t.ToString())) {
                    v.MinimumAntalVare = minInd;
                    return true;
                }
            }
            return false;
        }


        private void tælVare(int antal, Vare t) {
            foreach (VareTæller v in _tællerListe) {
                if (v.VareAtTjekke.ToString().Equals(t.ToString())) {
                    v.AntalVare += antal ;
                    if (antal < 0) { //tjekker om vi fjerner varer
                        //hvis antallet af vare er under minimums antal raiser vi et event
                        if (v.AntalVare < v.MinimumAntalVare) eventObj.VareAtTjekke = v; 
                    }
                    break;
                }
            }

            
        }

        public void UdskrivAntalVare() {
            foreach (VareTæller v in _tællerListe) Console.WriteLine(v.VareAtTjekke.Navn + " der er " + v.AntalVare);
        }
        #endregion

        //metode der bliver kaldt når eventet EfterVareErMinimum bliver raised
        public void VareAntalNåetMin(object sender, Events.VareTællerArgs e) {  
            Tilføj(e.VareAtTjekke.VareAtTjekke, e.VareAtTjekke.ØnsketAntal);
            Console.WriteLine(e.VareAtTjekke.VareAtTjekke.Navn + " løb tør for vare, " + e.VareAtTjekke.ØnsketAntal + " nye er tilføjet!");
        }

    }
}
